﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using CTP.Command;
using CTP.Entitys;
using CTP.Exceptions;
using CTP.Utilty;
using CTPAPI;

namespace CTP.Session
{
    /// <summary>
    /// 功能：Session的作用是提供客户系统接口与上期API之间的连接及对话功能。
    ///       Session接收对外接口中传递进来的命令，按照命令的类型，发送到上期API相应的接口中
    /// 创建：陈粤雄 20120428
    /// </summary>
    internal class Session : CThostFtdcTraderSpiWrapper
    {
        #region 字段
        /// <summary>
        /// 当前缓存命令的队列，是线程安全的
        /// </summary>
        private ConcurrentQueue<IRequestCommand> m_cmdQueue = new ConcurrentQueue<IRequestCommand>();

        /// <summary>
        /// 上期API实例
        /// </summary>
        private CThostFtdcTraderApiWrapper m_ctpApi;

        /// <summary>
        /// 命令出队列线程
        /// </summary>
        private Thread m_dequeueThread;

        /// <summary>
        /// 当前命令发送速度，只在单个线程中使用，不必考虑线程安全
        /// </summary>
        private int m_currentSpeed = 0;

        /// <summary>
        /// 最近清空速度计数器的时间
        /// </summary>
        private DateTime m_lastClearSpeedTime = DateTime.Now;

        /// <summary>
        /// 柜台连接事件，当开始连接时，阻塞进程，连接成功时，继续进程
        /// </summary>
        private ManualResetEvent m_connectEvent = new ManualResetEvent(false);

        /// <summary>
        /// 验证事件，当登陆时，阻塞进程， 验证成功时，再继续登陆
        /// </summary>
        private ManualResetEvent m_authEvent = new ManualResetEvent(false);

        /// <summary>
        /// 最近的登陆命令
        /// </summary>
        private LoginCmd m_lastLoginCmd = null;

        /// <summary>
        /// 是否已经认证客户端
        /// </summary>
        private bool m_isAuthenticated = false;

        #endregion

        #region 属性
        /// <summary>
        /// 获取当前会话的资金账号
        /// </summary>
        public string TradingAccount { get; private set; }

        /// <summary>
        /// 获取当前会话状态(线程安全)
        /// </summary>
        public bool IsConnected
        {
            get { lock (isConnectedSync) { return isConnected; } }
            private set { lock (isConnectedSync) { isConnected = value; } }
        }
        private bool isConnected = false;
        private object isConnectedSync = new object();

        /// <summary>
        /// 是否已登陆(线程安全)
        /// </summary>
        public bool IsLogined
        {
            get { lock (isLoginedSync) { return isLogined; } }
            private set { lock (isLoginedSync) { isLogined = value; } }
        }
        private bool isLogined = false;
        private object isLoginedSync = new object();

        /// <summary>
        /// 获取缓存合约与合约所在的市场的关联。当下单回调时，会在回调的信息中包含合约所属的市场。
        /// </summary>
        public ConcurrentDictionary<string, string> DictContractExchange { get; private set; }

        /// <summary>
        /// 获取前置登陆号,必须在登陆完才有值
        /// </summary>
        public int FrontID { get; private set; }

        /// <summary>
        /// 获取会话ID,必须在登陆完才有值
        /// </summary>
        public int SessionID { get; private set; }

        #endregion

        #region 构造
        /// <summary>
        /// 以指定资金账号构造会话
        /// </summary>
        /// <param name="tradingAccount"></param>
        public Session(string tradingAccount)
        {
            TradingAccount = tradingAccount;

            IsConnected = false;
            IsLogined = false;

            initializeCtpApi();

            m_dequeueThread = new Thread(new ThreadStart(procQueue));
            m_dequeueThread.IsBackground = true;
            m_dequeueThread.Start();

            connetctCtpApi();
        }
        #endregion

        #region 公开方法
        /// <summary>
        /// 执行一个会话命令
        /// </summary>
        /// <param name="cmd"></param>
        public int Excute(IRequestCommand cmd)
        {
            if (!IsConnected)
            {
                string errorStr = string.Format("与上期柜台没连接，或连接已断开，或已登出，请等待重新连接或重新登陆");
                Logger.Instance.WriteError(errorStr);
                ResponseManager.Instance.OnError(this.TradingAccount, ReturnInfo.Create(false, ErrorCode.UnConnected), -1);

                // 下单撤单拒绝
                if (cmd is PlaceOrderCmd)
                    OnRspOrderErrorNoConnected(cmd as PlaceOrderCmd, errorStr);
                else if (cmd is CancelOrderCmd)
                    OnRspOrderErrorNoConnected(cmd as CancelOrderCmd, errorStr);

                return ErrorCode.UnConnected;
            }
            else if (!IsLogined && !(cmd is LoginCmd))
            {
                string errorStr = string.Format("资金账号未登陆，或连接已断开，请重新登陆");
                Logger.Instance.WriteError(errorStr);
                ResponseManager.Instance.OnError(this.TradingAccount, ReturnInfo.Create(false, ErrorCode.NotLogin), -1);

                // 下单撤单拒绝
                if (cmd is PlaceOrderCmd)
                    OnRspOrderErrorNoLogined(cmd as PlaceOrderCmd, errorStr);
                else if (cmd is CancelOrderCmd)
                    OnRspOrderErrorNoLogined(cmd as CancelOrderCmd, errorStr);

                return ErrorCode.NotLogin;
            }

            m_cmdQueue.Enqueue(cmd);
            return ErrorCode.Success;
        }

        #endregion

        #region 私有方法 - 队列处理
        /// <summary>
        /// 队列处理，轮询命令队列，如果队列中有命令则马上处理
        /// </summary>
        private void procQueue()
        {
            IRequestCommand cmd;
            while (true)
            {
                while (IsConnected && m_cmdQueue.TryDequeue(out cmd))
                {
                    // 如果没登陆，且不是登陆命令，则不处理
                    if (cmd is LoginCmd || IsLogined)
                    {
                        Logger.Instance.WriteDebug("正在处理请求" + cmd.ToString());
                        try
                        {
                            procCmd(cmd);
                        }
                        catch (Exception ex)
                        {
                            Logger.Instance.WriteInfo("未处理的异常，" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace);
                        }
                    }
                    else
                    {
                        Thread.Sleep(100);
                        continue;
                    }

                    // 如果开启了速度限制，则计算当前速度，并对其限制
                    try
                    {
                        if (Config.Instance.SendSpeed > 0)
                        {
                            // 速度计算
                            m_currentSpeed += 1;

                            // 如果当前发送数超过配置的发送速度，且离上次清空计数器时间不足一秒，则说明发送速度超出了限制，
                            // 但如果超过一秒则不必理会，清空
                            if (m_currentSpeed > Config.Instance.SendSpeed)
                            {
                                int timeOffset = (int)(DateTime.Now.Subtract(m_lastClearSpeedTime).TotalMilliseconds);
                                if (timeOffset < 1000)
                                {
                                    // 暂停发送，等待到下一秒再发送
                                    Thread.Sleep(1000 - timeOffset);
                                    m_currentSpeed = 0;
                                }
                                else
                                {
                                    m_currentSpeed = 0;
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Logger.Instance.WriteInfo("未处理的异常，" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace);
                    }
                }

                Thread.Sleep(1);
            }
        }

        /// <summary>
        /// 处理一个命令，按照命令的不同类型，有不同的处理方法
        /// </summary>
        /// <param name="cmd"></param>
        private void procCmd(IRequestCommand cmd)
        {
            if (cmd is LoginCmd)
                login(cmd as LoginCmd);

            if (cmd is LogoutCmd)
                logout(cmd as LogoutCmd);

            else if (cmd is PlaceOrderCmd)
                placeOrder(cmd as PlaceOrderCmd);

            else if (cmd is ConfirmSettlementCmd)
                confirmSettlement(cmd as ConfirmSettlementCmd);

            else if (cmd is CancelOrderCmd)
                cancelOrder(cmd as CancelOrderCmd);

            else if (cmd is QueryAccountSummaryCmd)
                queryAccountSummary(cmd as QueryAccountSummaryCmd);

            else if (cmd is QueryHistoricalFilledCmd)
                queryHistoricalFilled(cmd as QueryHistoricalFilledCmd);

            else if (cmd is QueryHistoricalOrderRequestCmd)
                queryHistoricalOrderRequest(cmd as QueryHistoricalOrderRequestCmd);

            else if (cmd is QueryOrderStatusCmd)
                queryOrderStatus(cmd as QueryOrderStatusCmd);

            else if (cmd is QueryPositionCmd)
                queryPosition(cmd as QueryPositionCmd);

            else if (cmd is QuerySettlementCmd)
                querySettlement(cmd as QuerySettlementCmd);

            else if (cmd is QueryTodayFilledCmd)
                queryTodayFilled(cmd as QueryTodayFilledCmd);

            else if (cmd is QueryTodayOrderRequestCmd)
                queryTodayOrderRequest(cmd as QueryTodayOrderRequestCmd);

            else if (cmd is PlaceOrderBatchCmd)
                placeOrderBatch(cmd as PlaceOrderBatchCmd);
        }
        #endregion

        #region 私有方法 - 上期API实例初始化、连接

        private int initializeCtpApi()
        {
            try
            {
                // 指定会话文件
                string currentDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
                string conFilePath = Path.Combine(currentDir, "ctpcon\\" + TradingAccount + "\\");
                if (!Directory.Exists(conFilePath))
                    Directory.CreateDirectory(conFilePath);

                // 构造上期API实例
                m_ctpApi = new CThostFtdcTraderApiWrapper(conFilePath);
                m_ctpApi.RegisterSpi(this);
                m_ctpApi.SubscribePrivateTopic((int)SubscribeType.TERT_QUICK);

                // 连接到指定地址
                string address = Config.Instance.ConnectAddress + ":" + Config.Instance.ConnectPort;
                m_ctpApi.RegisterFront(address);
                m_ctpApi.Init();

                return ErrorCode.Success;
            }
            catch (Exception ex)
            {
                Logger.Instance.WriteInfo("未处理的异常，" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace);
                return ErrorCode.UnHandle;
            }
        }

        // 与柜台连接
        private int connetctCtpApi()
        {
            try
            {
                string address = Config.Instance.ConnectAddress + ":" + Config.Instance.ConnectPort;

                // 必须以新的线程来Join上期柜台
                m_connectEvent.Reset();
                Thread joinThread = new Thread(new ThreadStart(delegate()
                  {
                      Logger.Instance.WriteDebug("资金账号：" + this.TradingAccount + "正在发送连接请求，地址:" + address);

                      try
                      {
                          m_ctpApi.Join();
                      }
                      catch (Exception ex)
                      {
                          string errorStr = string.Format("资金账号：{0} 与上期柜台连接异常，地址:{1}，异常信息:{2}", this.TradingAccount, address, ex.GetBaseException());
                          Logger.Instance.WriteError(errorStr);
                          Logger.Instance.WriteError(string.Format("资金账号：{0}与上期柜台连接失败，正在重新连接，地址:{1}", this.TradingAccount, address));
                          ResponseManager.Instance.OnError(this.TradingAccount, ReturnInfo.Create(false, ErrorCode.ConnectFailt), -1);
                      }
                  }));
                joinThread.IsBackground = true;
                joinThread.Start();

                // 阻塞当前线程，直到连接成功或连接超时
                if (!m_connectEvent.WaitOne(Config.Instance.ConnectTimeout))
                {
                    string errorStr = string.Format("资金账号：{0} 与上期柜台连接超时，地址:{1}，超过{2}毫秒无响应", this.TradingAccount, address, Config.Instance.ConnectTimeout);
                    Logger.Instance.WriteError(errorStr);
                    ResponseManager.Instance.OnError(this.TradingAccount, ReturnInfo.Create(false, ErrorCode.ConnectTimeout), -1);
                    return ErrorCode.ConnectTimeout;
                }

                return ErrorCode.Success;
            }
            catch (Exception ex)
            {
                Logger.Instance.WriteInfo("未处理的异常，" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace);
                return ErrorCode.UnHandle;
            }
        }
        #endregion

        #region 私有方法 - 请求处理 -登入登出

        /// <summary>
        /// 资金账号登陆
        /// </summary>
        private void login(LoginCmd loginCmd)
        {
            CThostFtdcReqUserLoginFieldWrapper loginField = FieldConverter.ToCThostFtdcReqUserLoginFieldWrapper(loginCmd.TradingAccount);
            loginField.TradingDay = m_ctpApi.GetTradingDay();
            int result = 0;

            try
            {
                // 发送认证请求============================
                if (!m_isAuthenticated && !string.IsNullOrEmpty(loginCmd.TradingAccount.AuthCode))
                {
                    CThostFtdcReqAuthenticateFieldWrapper authReq = new CThostFtdcReqAuthenticateFieldWrapper();
                    authReq.BrokerID = loginCmd.TradingAccount.BranchNO;
                    authReq.UserID = loginCmd.TradingAccount.UserAccount;
                    authReq.AuthCode = loginCmd.TradingAccount.AuthCode;
                    result = m_ctpApi.ReqAuthenticate(authReq, loginCmd.RequestID);

                    // 等待认证完成
                    if (!m_authEvent.WaitOne(5000) || !m_isAuthenticated)
                    {
                        string errStr = string.Format("客户端认证失败,无法登陆，资金账号:{0}，RequestID:{1}，result:{2},AuthCode:{3},BranchNO:{4}",
                            loginCmd.TradingAccount.UserAccount, loginCmd.RequestID, result, loginCmd.TradingAccount.AuthCode, loginCmd.TradingAccount.BranchNO);
                        ReturnInfo returnInfo = ReturnInfo.Create(false, ErrorCode.LoginCmdSendFailt, errStr);
                        Logger.Instance.WriteError(returnInfo.ErrorMessage);
                        ResponseManager.Instance.OnError(this.TradingAccount, returnInfo, loginCmd.RequestID);
                        return;
                    }
                }

                // 发送登陆请求============================ 
                result = m_ctpApi.ReqUserLogin(loginField, loginCmd.RequestID);
                Logger.Instance.WriteInfo(string.Format("已发送登陆请求，资金账号:{0}，RequestID:{1}，result:{2}", loginCmd.TradingAccount.UserAccount, loginCmd.RequestID, result));

                // 发送登陆请求失败
                if (result != 0)
                {
                    m_lastLoginCmd = null;
                    ReturnInfo returnInfo = ReturnInfo.Create(false, ErrorCode.LoginCmdSendFailt);
                    Logger.Instance.WriteError(returnInfo.ErrorMessage);
                    ResponseManager.Instance.OnError(this.TradingAccount, returnInfo, loginCmd.RequestID);
                }
                // 发送登陆成功
                else
                {
                    m_lastLoginCmd = loginCmd;
                }
            }
            catch (Exception ex)
            {
                ReturnInfo returnInfo = ReturnInfo.Create(false, ErrorCode.UnHandle, ex.Message);
                Logger.Instance.WriteError(returnInfo.ErrorMessage);
                ResponseManager.Instance.OnError(this.TradingAccount, returnInfo, loginCmd.RequestID);
            }
        }

        /// <summary>
        /// 资金账号登出
        /// </summary>
        private void logout(LogoutCmd logoutCmd)
        {
            // 如果未登陆，则发出登出错误
            if (!this.IsLogined)
            {
                ReturnInfo returnInfo = ReturnInfo.Create(false, ErrorCode.NotLogin);
                Logger.Instance.WriteError(returnInfo.ErrorMessage);
                ResponseManager.Instance.OnError(this.TradingAccount, returnInfo, logoutCmd.RequestID);
            }
            else
            {
                CThostFtdcUserLogoutFieldWrapper logoutField = FieldConverter.ToCThostFtdcReqUserLogoutFieldWrapper(logoutCmd.TradingAccount);
                int result = 0;

                try
                {
                    // 发送登出请求
                    result = m_ctpApi.ReqUserLogout(logoutField, logoutCmd.RequestID);

                    Logger.Instance.WriteInfo(string.Format("已发送登出请求，资金账号:{0}，RequestID:{1}，result:{2}", logoutCmd.TradingAccount.UserAccount, logoutCmd.RequestID, result));
                    // 发送登出请求失败
                    if (result != 0)
                    {
                        ReturnInfo returnInfo = ReturnInfo.Create(false, ErrorCode.LogoutCmdSendFailt);
                        Logger.Instance.WriteError(returnInfo.ErrorMessage);
                        ResponseManager.Instance.OnError(this.TradingAccount, returnInfo, logoutCmd.RequestID);
                    }
                }
                catch (Exception ex)
                {
                    ReturnInfo returnInfo = ReturnInfo.Create(false, ErrorCode.UnHandle, ex.Message);
                    Logger.Instance.WriteError(returnInfo.ErrorMessage);
                    ResponseManager.Instance.OnError(this.TradingAccount, returnInfo, logoutCmd.RequestID);
                }
            }
        }
        #endregion

        #region 私有方法 - 请求处理 -帐户
        /// <summary>
        /// 查询结算信息(帐户概览)
        /// </summary>      
        private void querySettlement(QuerySettlementCmd cmd)
        {
            CThostFtdcQrySettlementInfoConfirmFieldWrapper querySettlementField = FieldConverter.ToCThostFtdcQrySettlementInfoConfirmFieldWrapper(cmd.TradingAccount);
            int result = 0;

            try
            {
                // 发送请求
                result = m_ctpApi.ReqQrySettlementInfoConfirm(querySettlementField, cmd.RequestID);
                Logger.Instance.WriteInfo(string.Format("已发送查询结算信息请求，资金账号:{0}，RequestID:{1}，result:{2}", cmd.TradingAccount.UserAccount, cmd.RequestID, result));

                // 发送请求失败
                if (result != 0)
                {
                    ReturnInfo returnInfo = ReturnInfo.Create(false, ErrorCode.QrySettlementCmdSendFailt);
                    Logger.Instance.WriteError(returnInfo.ErrorMessage);
                    ResponseManager.Instance.OnError(this.TradingAccount, returnInfo, cmd.RequestID);
                }
            }
            catch (Exception ex)
            {
                ReturnInfo returnInfo = ReturnInfo.Create(false, ErrorCode.UnHandle, ex.Message);
                Logger.Instance.WriteError(returnInfo.ErrorMessage);
                ResponseManager.Instance.OnError(this.TradingAccount, returnInfo, cmd.RequestID);
            }
        }

        /// <summary>
        /// 确认结算信息
        /// </summary>
        private void confirmSettlement(ConfirmSettlementCmd cmd)
        {
            CThostFtdcSettlementInfoConfirmFieldWrapper confirmSettlementField = FieldConverter.ToCThostFtdcSettlementInfoConfirmFieldWrapper(cmd.TradingAccount);
            int result = 0;

            try
            {
                // 发送请求
                result = m_ctpApi.ReqSettlementInfoConfirm(confirmSettlementField, cmd.RequestID);
                Logger.Instance.WriteInfo(string.Format("已发送确认结算信息请求，资金账号:{0}，RequestID:{1}，result:{2}", cmd.TradingAccount.UserAccount, cmd.RequestID, result));

                // 发送请求失败
                if (result != 0)
                {
                    ReturnInfo returnInfo = ReturnInfo.Create(false, ErrorCode.ConfirmSettlementCmdSendFailt);
                    Logger.Instance.WriteError(returnInfo.ErrorMessage);
                    ResponseManager.Instance.OnError(this.TradingAccount, returnInfo, cmd.RequestID);
                }
            }
            catch (Exception ex)
            {
                ReturnInfo returnInfo = ReturnInfo.Create(false, ErrorCode.UnHandle, ex.Message);
                Logger.Instance.WriteError(returnInfo.ErrorMessage);
                ResponseManager.Instance.OnError(this.TradingAccount, returnInfo, cmd.RequestID);
            }
        }


        /// <summary>
        /// 查询帐户概览
        /// </summary>       
        private void queryAccountSummary(QueryAccountSummaryCmd cmd)
        {
            CThostFtdcQryTradingAccountFieldWrapper qryTradingAccountField = FieldConverter.ToCThostFtdcQryTradingAccountFieldWrapper(cmd.TradingAccount);
            int result = 0;

            try
            {
                // 发送请求
                result = m_ctpApi.ReqQryTradingAccount(qryTradingAccountField, cmd.RequestID);
                Logger.Instance.WriteInfo(string.Format("已发送查询帐户概览请求，资金账号:{0}，RequestID:{1}，result:{2}", cmd.TradingAccount.UserAccount, cmd.RequestID, result));

                // 发送请求失败
                if (result != 0)
                {
                    ReturnInfo returnInfo = ReturnInfo.Create(false, ErrorCode.QueryAccountSummaryCmdSendFailt);
                    Logger.Instance.WriteError(returnInfo.ErrorMessage);
                    ResponseManager.Instance.OnError(this.TradingAccount, returnInfo, cmd.RequestID);
                }
            }
            catch (Exception ex)
            {
                ReturnInfo returnInfo = ReturnInfo.Create(false, ErrorCode.UnHandle, ex.Message);
                Logger.Instance.WriteError(returnInfo.ErrorMessage);
                ResponseManager.Instance.OnError(this.TradingAccount, returnInfo, cmd.RequestID);
            }
        }
        #endregion

        #region 私有方法 - 请求处理 -下单撤单

        /// <summary>
        /// 下单
        /// </summary>    
        private void placeOrder(PlaceOrderCmd cmd)
        {
            CThostFtdcInputOrderFieldWrapper orderField = FieldConverter.ToCThostFtdcInputOrderFieldWrapper(cmd.Order, cmd.TradingAccount);
            int result = 0;
            string orderInfo = string.Format(
                    "已发送下单请求，资金账号:{0}，代码:{1}，数量:{2}，RequestID:{3}，result:{4}",
                    cmd.TradingAccount.UserAccount,
                    cmd.Order.Code,
                    cmd.Order.Amount,
                    cmd.RequestID,
                    result);

            try
            {
                // 发送请求
                result = m_ctpApi.ReqOrderInsert(orderField, cmd.RequestID);
                Logger.Instance.WriteInfo(orderInfo);

                // 发送请求失败
                if (result != 0)
                {
                    ReturnInfo returnInfo = ReturnInfo.Create(false, ErrorCode.PlaceOrderCmdSendFailt, orderInfo);
                    Logger.Instance.WriteError(returnInfo.ErrorMessage);
                    ResponseManager.Instance.OnError(this.TradingAccount, returnInfo, cmd.RequestID);
                }
            }
            catch (Exception ex)
            {
                ReturnInfo returnInfo = ReturnInfo.Create(false, ErrorCode.UnHandle, ex.Message);
                Logger.Instance.WriteError(returnInfo.ErrorMessage);
                ResponseManager.Instance.OnError(this.TradingAccount, returnInfo, cmd.RequestID);
            }
        }
        /// <summary>
        /// 下单
        /// </summary>    
        private void placeOrderBatch(PlaceOrderBatchCmd cmd)
        {
            throw new NotImplementedException("上期不支持批量下单");
        }
        /// <summary>
        /// 撤单
        /// </summary>      
        private void cancelOrder(CancelOrderCmd cmd)
        {
            CThostFtdcInputOrderActionFieldWrapper orderCancelField = new CThostFtdcInputOrderActionFieldWrapper();
            orderCancelField.OrderSysID = cmd.CancelOrderInfo.OrderID.Trim().PadLeft(12);
            orderCancelField.InstrumentID = cmd.TradingAccount.UserAccount;
            orderCancelField.BrokerID = cmd.TradingAccount.BranchNO;
            orderCancelField.ActionFlag = (sbyte)TFtdcActionFlag.THOST_FTDC_AF_Delete;
            orderCancelField.ExchangeID = cmd.CancelOrderInfo.ExchangeID.Trim();
            orderCancelField.OrderRef = cmd.CancelOrderInfo.OrderRef;

            int result = 0;
            string info = string.Format(
                    "已发送撤单请求，资金账号:{0}，OrderID:{1},RequestID:{2}，result:{3},OrderRef={4}",
                    cmd.TradingAccount.UserAccount,
                    cmd.CancelOrderInfo.OrderID.Trim(),
                    cmd.RequestID,
                    result,
                    cmd.CancelOrderInfo.OrderRef);

            try
            {
                // 发送请求
                result = m_ctpApi.ReqOrderAction(orderCancelField, cmd.RequestID);
                Logger.Instance.WriteInfo(info);

                // 发送请求失败
                if (result != 0)
                {
                    ReturnInfo returnInfo = ReturnInfo.Create(false, ErrorCode.CancelOrderCmdSendFailt, info);
                    Logger.Instance.WriteError(returnInfo.ErrorMessage);
                    ResponseManager.Instance.OnError(this.TradingAccount, returnInfo, cmd.RequestID);
                }
            }
            catch (Exception ex)
            {
                ReturnInfo returnInfo = ReturnInfo.Create(false, ErrorCode.UnHandle, ex.Message);
                Logger.Instance.WriteError(returnInfo.ErrorMessage);
                ResponseManager.Instance.OnError(this.TradingAccount, returnInfo, cmd.RequestID);
            }
        }

        #endregion

        #region 私有方法 - 请求处理 - 查询
        /// <summary>
        /// 查单状态
        /// </summary>      
        private void queryOrderStatus(QueryOrderStatusCmd cmd)
        {
            CThostFtdcQryOrderFieldWrapper orderQueryField = FieldConverter.ToCThostFtdcQryOrderFieldWrapper(cmd.Order, cmd.TradingAccount);
            int result = 0;
            string orderInfo = string.Format(
                    "已发送查单状态请求，资金账号:{0}，代码:{1}，OrderID:{4},RequestID:{2}，result:{3}",
                    cmd.TradingAccount.UserAccount,
                    cmd.Order.Code,
                    cmd.RequestID,
                    result,
                    cmd.Order.OrderID);

            try
            {
                // 发送请求
                result = m_ctpApi.ReqQryOrder(orderQueryField, cmd.RequestID);
                Logger.Instance.WriteInfo(orderInfo);

                // 发送请求失败
                if (result != 0)
                {
                    ReturnInfo returnInfo = ReturnInfo.Create(false, ErrorCode.QueryOrderStatusCmdSendFailt, orderInfo);
                    Logger.Instance.WriteError(returnInfo.ErrorMessage);
                    ResponseManager.Instance.OnError(this.TradingAccount, returnInfo, cmd.RequestID);
                }
            }
            catch (Exception ex)
            {
                ReturnInfo returnInfo = ReturnInfo.Create(false, ErrorCode.UnHandle, ex.Message);
                Logger.Instance.WriteError(returnInfo.ErrorMessage);
                ResponseManager.Instance.OnError(this.TradingAccount, returnInfo, cmd.RequestID);
            }
        }

        /// <summary>
        /// 查询当日委托
        /// </summary>     
        private void queryTodayOrderRequest(QueryTodayOrderRequestCmd cmd)
        {
            CThostFtdcQryOrderFieldWrapper qryTodayOrder = new CThostFtdcQryOrderFieldWrapper();
            qryTodayOrder.BrokerID = cmd.TradingAccount.BranchNO;
            qryTodayOrder.InvestorID = cmd.TradingAccount.UserAccount;
            int result = 0;
            string info = string.Format(
                    "已发送查询当日委托请求，资金账号:{0}，RequestID:{1}，result:{2}",
                    cmd.TradingAccount.UserAccount,
                    cmd.RequestID,
                    result);

            try
            {
                // 发送请求
                result = m_ctpApi.ReqQryOrder(qryTodayOrder, cmd.RequestID);
                Logger.Instance.WriteInfo(info);

                // 发送请求失败
                if (result != 0)
                {
                    ReturnInfo returnInfo = ReturnInfo.Create(false, ErrorCode.QueryTodayOrderRequestCmdSendFailt, info);
                    Logger.Instance.WriteError(returnInfo.ErrorMessage);
                    ResponseManager.Instance.OnError(this.TradingAccount, returnInfo, cmd.RequestID);
                }
            }
            catch (Exception ex)
            {
                ReturnInfo returnInfo = ReturnInfo.Create(false, ErrorCode.UnHandle, ex.Message);
                Logger.Instance.WriteError(returnInfo.ErrorMessage);
                ResponseManager.Instance.OnError(this.TradingAccount, returnInfo, cmd.RequestID);
            }
        }

        /// <summary>
        /// 查询历史委托
        /// </summary>      
        private void queryHistoricalOrderRequest(QueryHistoricalOrderRequestCmd cmd)
        {
            throw new NotImplementedException("上期柜台不支持查历史委托");
        }

        /// <summary>
        /// 查询当日成交
        /// </summary>       
        private void queryTodayFilled(QueryTodayFilledCmd cmd)
        {
            CThostFtdcQryTradeFieldWrapper field = new CThostFtdcQryTradeFieldWrapper();
            field.BrokerID = cmd.TradingAccount.BranchNO;
            field.InvestorID = cmd.TradingAccount.UserAccount;
            int result = 0;
            string info = string.Format(
                    "已发送查询当日成交请求，资金账号:{0}，RequestID:{1}，result:{2}",
                    cmd.TradingAccount.UserAccount,
                    cmd.RequestID,
                    result);

            try
            {
                // 发送请求
                result = m_ctpApi.ReqQryTrade(field, cmd.RequestID);
                Logger.Instance.WriteInfo(info);

                // 发送请求失败
                if (result != 0)
                {
                    ReturnInfo returnInfo = ReturnInfo.Create(false, ErrorCode.QueryTodayFilledCmdSendFailt, info);
                    Logger.Instance.WriteError(returnInfo.ErrorMessage);
                    ResponseManager.Instance.OnError(this.TradingAccount, returnInfo, cmd.RequestID);
                }
            }
            catch (Exception ex)
            {
                ReturnInfo returnInfo = ReturnInfo.Create(false, ErrorCode.UnHandle, ex.Message);
                Logger.Instance.WriteError(returnInfo.ErrorMessage);
                ResponseManager.Instance.OnError(this.TradingAccount, returnInfo, cmd.RequestID);
            }
        }

        /// <summary>
        /// 查询历史成交
        /// </summary>     
        private void queryHistoricalFilled(QueryHistoricalFilledCmd cmd)
        {
            throw new NotImplementedException("上期柜台不支持查历史委托");
        }

        /// <summary>
        /// 查询持仓/库存
        /// </summary>      
        private void queryPosition(QueryPositionCmd cmd)
        {
            CThostFtdcQryInvestorPositionFieldWrapper field = FieldConverter.ToCThostFtdcQryInvestorPositionFieldWrapper(cmd.TradingAccount);
            int result = 0;
            string info = string.Format(
                    "已发送查询持仓/库存请求，资金账号:{0}，RequestID:{1}，result:{2}",
                    cmd.TradingAccount.UserAccount,
                    cmd.RequestID,
                    result);

            try
            {
                // 发送请求
                result = m_ctpApi.ReqQryInvestorPosition(field, cmd.RequestID);
                Logger.Instance.WriteInfo(info);

                // 发送请求失败
                if (result != 0)
                {
                    ReturnInfo returnInfo = ReturnInfo.Create(false, ErrorCode.QueryPositionCmdSendFailt, info);
                    Logger.Instance.WriteError(returnInfo.ErrorMessage);
                    ResponseManager.Instance.OnError(this.TradingAccount, returnInfo, cmd.RequestID);
                }
            }
            catch (Exception ex)
            {
                ReturnInfo returnInfo = ReturnInfo.Create(false, ErrorCode.UnHandle, ex.Message);
                Logger.Instance.WriteError(returnInfo.ErrorMessage);
                ResponseManager.Instance.OnError(this.TradingAccount, returnInfo, cmd.RequestID);
            }
        }
        #endregion


        #region 私有方法 - 回报 - 连接、登陆、认证
        // 连接成功通知
        void CThostFtdcTraderSpiWrapper.OnFrontConnected()
        {
            try
            {
                this.IsConnected = true;
                m_connectEvent.Set();
                Logger.Instance.WriteInfo(string.Format("资账号{0}与上期柜台连接成功", this.TradingAccount));

                if (m_lastLoginCmd != null)
                {
                    Logger.Instance.WriteInfo(string.Format("资账号{0}正在重新登陆...", this.TradingAccount));
                    login(m_lastLoginCmd);
                }
            }
            catch (Exception ex)
            {
                Logger.Instance.WriteInfo("未处理的异常，" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace);
            }
        }

        // 连接断开通知
        void CThostFtdcTraderSpiWrapper.OnFrontDisconnected(int nReason)
        {
            try
            {
                this.IsConnected = false;
                this.IsLogined = false;
                Logger.Instance.WriteInfo(string.Format("资账号{0}与上期柜台连接断开,原因:{1}", this.TradingAccount, nReason));
            }
            catch (Exception ex)
            {
                Logger.Instance.WriteInfo("未处理的异常，" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace);
            }
        }

        // 登陆回报
        void CThostFtdcTraderSpiWrapper.OnRspUserLogin(CThostFtdcRspUserLoginFieldWrapper pRspUserLogin, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            try
            {
                if (pRspInfo == null || pRspInfo.ErrorID == 0)
                {
                    // 登陆成功
                    this.IsLogined = true;
                    this.FrontID = pRspUserLogin.FrontID;
                    this.SessionID = pRspUserLogin.SessionID;

                    LoginInfo loginInfo = new LoginInfo()
                    {
                        TradingAccount = this.TradingAccount,
                        IsLogined = true
                    };

                    Logger.Instance.WriteInfo(string.Format("资账号{0}登陆成功,requestID={1},FrontID={2},SessionID={3}", this.TradingAccount, nRequestID, pRspUserLogin.FrontID, pRspUserLogin.SessionID));
                    ResponseManager.Instance.OnLogin(this.TradingAccount, ReturnInfo.Create(true, 0), loginInfo, nRequestID);
                }
                else
                {
                    this.IsLogined = false;

                    LoginInfo loginInfo = new LoginInfo()
                    {
                        TradingAccount = this.TradingAccount,
                        IsLogined = false
                    };

                    Logger.Instance.WriteInfo(string.Format("资账号{0}登陆失败,requestID={1},FrontID={2},SessionID={3},原因={4}", this.TradingAccount, nRequestID, pRspUserLogin.FrontID, pRspUserLogin.SessionID, pRspInfo.ErrorMsg));
                    ResponseManager.Instance.OnLogin(this.TradingAccount, ReturnInfo.Create(false, ErrorCode.LoginFailt, pRspInfo.ErrorMsg), loginInfo, nRequestID);
                }
            }
            catch (Exception ex)
            {
                Logger.Instance.WriteInfo("未处理的异常，" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace);
            }
        }

        // 登出回报
        void CThostFtdcTraderSpiWrapper.OnRspUserLogout(CThostFtdcUserLogoutFieldWrapper pUserLogout, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            try
            {
                if (pRspInfo == null || pRspInfo.ErrorID == 0)
                {
                    // 登陆成功
                    this.IsLogined = false;
                    this.FrontID = 0;
                    this.SessionID = 0;
                    ResponseManager.Instance.OnLogout(this.TradingAccount, ReturnInfo.Create(true, 0), nRequestID);
                }
                else
                {
                    Logger.Instance.WriteInfo(string.Format("资账号{0}登出失败,requestID={1},原因={2}", this.TradingAccount, nRequestID, pRspInfo.ErrorMsg));
                    ResponseManager.Instance.OnLogout(this.TradingAccount, ReturnInfo.Create(false, ErrorCode.LoginFailt, pRspInfo.ErrorMsg), nRequestID);
                }
            }
            catch (Exception ex)
            {
                Logger.Instance.WriteInfo("未处理的异常，" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace);
            }
        }

        // 验证回报
        void CThostFtdcTraderSpiWrapper.OnRspAuthenticate(CThostFtdcRspAuthenticateFieldWrapper pRspAuthenticateField, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            try
            {
                if (pRspInfo == null || pRspInfo.ErrorID == 0)
                {
                    m_isAuthenticated = true;
                    m_authEvent.Set();
                }
                else
                {
                    m_isAuthenticated = false;
                    m_authEvent.Set();
                    Logger.Instance.WriteInfo(string.Format("资账号{0}认证失败,requestID={1},原因={2},AuthCode={3}", this.TradingAccount, nRequestID, pRspInfo.ErrorMsg));
                }
            }
            catch (Exception ex)
            {
                Logger.Instance.WriteInfo("未处理的异常，" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace);
            }
        }
        #endregion

        #region 私有方法 - 回报 - 结算信息

        // 查结算信息
        void CThostFtdcTraderSpiWrapper.OnRspQrySettlementInfoConfirm(CThostFtdcSettlementInfoConfirmFieldWrapper pSettlementInfoConfirm, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            try
            {

                Logger.Instance.WriteInfo(string.Format("资金账号{1}查结算信息响应,requestID={0}", nRequestID, this.TradingAccount));

                ReturnInfo returnInfo;
                SettlementInfoConfirm ConfirmInfo;
                if (pSettlementInfoConfirm != null && (pRspInfo == null || pRspInfo.ErrorID == 0))
                {
                    returnInfo = ReturnInfo.Create(true, 0);
                    ConfirmInfo = new SettlementInfoConfirm()
                    {
                        ConfirmDateTime = pSettlementInfoConfirm.ConfirmDate + " " + pSettlementInfoConfirm.ConfirmTime,
                        IsConfirmed = (pSettlementInfoConfirm.ConfirmDate + pSettlementInfoConfirm.ConfirmTime) != "",
                        TradingAccount = pSettlementInfoConfirm.InvestorID
                    };
                }
                else
                {
                    if (pRspInfo != null)
                        returnInfo = ReturnInfo.Create(false, ErrorCode.QuerySettlementInfoFailt, pRspInfo.ErrorMsg);
                    else
                        returnInfo = ReturnInfo.Create(false, ErrorCode.QuerySettlementInfoFailt);

                    ConfirmInfo = new SettlementInfoConfirm()
                        {
                            ConfirmDateTime = "",
                            IsConfirmed = false,
                            TradingAccount = this.TradingAccount
                        };
                }

                Logger.Instance.WriteDebug(string.Format("回报查结算信息响应信息,requestID={0},TradingAccount={1},ConfirmDateTime={2},IsConfirmed={3}", nRequestID, this.TradingAccount, ConfirmInfo.ConfirmDateTime, ConfirmInfo.IsConfirmed));
                ResponseManager.Instance.OnQuerySettlementInfo(this.TradingAccount, ConfirmInfo, returnInfo, nRequestID);

            }
            catch (Exception ex)
            {
                Logger.Instance.WriteInfo("未处理的异常，" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace);
            }
        }

        // 确认结算信息
        void CThostFtdcTraderSpiWrapper.OnRspSettlementInfoConfirm(CThostFtdcSettlementInfoConfirmFieldWrapper pSettlementInfoConfirm, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            try
            {

                Logger.Instance.WriteInfo(string.Format("资金账号{1}确认结算信息响应,requestID={0}", nRequestID, this.TradingAccount));

                ReturnInfo returnInfo;
                if (pRspInfo == null || pRspInfo.ErrorID == 0)
                    returnInfo = ReturnInfo.Create(true, 0);
                else
                    returnInfo = ReturnInfo.Create(false, ErrorCode.ConfirmSettlementInfoFailt, pRspInfo.ErrorMsg);

                ResponseManager.Instance.OnConfirmSettlementInfo(this.TradingAccount, returnInfo, nRequestID);

            }
            catch (Exception ex)
            {
                Logger.Instance.WriteInfo("未处理的异常，" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace);
            }
        }
        #endregion

        #region 私有方法 - 回报 - 查询资金账户回报

        // 查询资金账户回报
        void CThostFtdcTraderSpiWrapper.OnRspQryTradingAccount(CThostFtdcTradingAccountFieldWrapper pTradingAccount, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            try
            {
                if (pRspInfo == null || pRspInfo.ErrorID == 0)
                {
                    // 查询成功
                    Logger.Instance.WriteInfo(string.Format("资金账号{0}查帐户概览成功,requestid={1}", this.TradingAccount, nRequestID));

                    AccountInformation summary = new AccountInformation();
                    summary.UserAccount = pTradingAccount.AccountID;
                    summary.PreMortgage = pTradingAccount.PreMortgage;
                    summary.PreCredit = pTradingAccount.PreCredit;
                    summary.PreDeposit = pTradingAccount.PreDeposit;
                    summary.PreBalance = pTradingAccount.PreBalance;
                    summary.PreMargin = pTradingAccount.PreMargin;
                    summary.InterestBase = pTradingAccount.InterestBase;
                    summary.Interest = pTradingAccount.Interest;
                    summary.Deposit = pTradingAccount.Deposit;
                    summary.Withdraw = pTradingAccount.Withdraw;
                    summary.FrozenMargin = pTradingAccount.FrozenMargin;
                    summary.FrozenCash = pTradingAccount.FrozenCash;
                    summary.FrozenCommission = pTradingAccount.FrozenCommission;
                    summary.CurrMargin = pTradingAccount.CurrMargin;
                    summary.CashIn = pTradingAccount.CashIn;
                    summary.Commission = pTradingAccount.Commission;
                    summary.CloseProfit = pTradingAccount.CloseProfit;
                    summary.PositionProfit = pTradingAccount.PositionProfit;
                    summary.Balance = pTradingAccount.Balance;
                    summary.Available = pTradingAccount.Available;
                    summary.WithdrawQuota = pTradingAccount.WithdrawQuota;
                    summary.Reserve = pTradingAccount.Reserve;
                    summary.Credit = pTradingAccount.Credit;
                    summary.Mortgage = pTradingAccount.Mortgage;
                    summary.ExchangeMargin = pTradingAccount.ExchangeMargin;

                    ReturnInfo returnInfo = ReturnInfo.Create(true, 0);
                    ResponseManager.Instance.OnAccountSummary(this.TradingAccount, returnInfo, summary, nRequestID);
                }
                else
                {
                    // 查询失败
                    Logger.Instance.WriteInfo(string.Format("资金账号{0}查帐户概览失败,requestid={1}，ErrorMsg={2}", this.TradingAccount, nRequestID, pRspInfo.ErrorMsg));

                    ReturnInfo returnInfo = ReturnInfo.Create(false, ErrorCode.QueryAccountInfoFailt, pRspInfo.ErrorMsg);
                    AccountInformation summary = new AccountInformation();
                    ResponseManager.Instance.OnAccountSummary(this.TradingAccount, returnInfo, summary, nRequestID);
                }

            }
            catch (Exception ex)
            {
                Logger.Instance.WriteInfo("未处理的异常，" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace);
            }
        }

        #endregion

        #region 私有方法 - 回报 - 报单回报

        //报单错误（未连接或未登陆）
        private void OnRspOrderErrorNoConnected(PlaceOrderCmd cmd, string message)
        {
            // 下单信息
            OrderStatus status = new OrderStatus();
            status.OrderID = "";
            status.OrderRef = cmd.Order.OrderRef;
            status.OrderState = OrderState.PlaceRejected;
            status.TimeStamp = "";
            status.Message = message; ;

            ReturnInfo returnInfo = ReturnInfo.Create(false, ErrorCode.PlaceOrderRejectByCTP, message);
            ResponseManager.Instance.OnOrderStatus(this.TradingAccount, returnInfo, status, cmd.RequestID);
        }

        //报单错误（未连接或未登陆）
        private void OnRspOrderErrorNoConnected(CancelOrderCmd cmd, string message)
        {
            // 下单信息
            OrderStatus status = new OrderStatus();
            status.OrderID = cmd.CancelOrderInfo.OrderID;
            status.OrderRef = cmd.CancelOrderInfo.OrderRef;
            status.OrderState = OrderState.CancelRejected;
            status.TimeStamp = "";
            status.Message = message; ;

            ReturnInfo returnInfo = ReturnInfo.Create(false, ErrorCode.CancelOrderRejectByCTP, message);
            ResponseManager.Instance.OnOrderStatus(this.TradingAccount, returnInfo, status, cmd.RequestID);
        }

        //撤单错误（未连接或未登陆）
        private void OnRspOrderErrorNoLogined(PlaceOrderCmd cmd, string message)
        {
            // 下单信息
            OrderStatus status = new OrderStatus();
            status.OrderID = "";
            status.OrderRef = cmd.Order.OrderRef;
            status.OrderState = OrderState.PlaceRejected;
            status.TimeStamp = "";
            status.Message = message;

            ReturnInfo returnInfo = ReturnInfo.Create(false, ErrorCode.PlaceOrderRejectByCTP, message);
            ResponseManager.Instance.OnOrderStatus(this.TradingAccount, returnInfo, status, cmd.RequestID);
        }

        //撤单错误（未连接或未登陆）
        private void OnRspOrderErrorNoLogined(CancelOrderCmd cmd, string message)
        {
            // 下单信息
            OrderStatus status = new OrderStatus();
            status.OrderID = cmd.CancelOrderInfo.OrderID;
            status.OrderRef = cmd.CancelOrderInfo.OrderRef;
            status.OrderState = OrderState.CancelRejected;
            status.TimeStamp = "";
            status.Message = message;

            ReturnInfo returnInfo = ReturnInfo.Create(false, ErrorCode.CancelOrderRejectByCTP, message);
            ResponseManager.Instance.OnOrderStatus(this.TradingAccount, returnInfo, status, cmd.RequestID);
        }

        //报单错误(CTP拒绝)
        void CThostFtdcTraderSpiWrapper.OnRspOrderInsert(CThostFtdcInputOrderFieldWrapper pInputOrder, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            try
            {
                Logger.Instance.WriteInfo(string.Format("资金账号{0}下单[CTP废单]响应,OrderRef={1},ErrorMsg={2}", this.TradingAccount, pInputOrder.OrderRef, pRspInfo.ErrorMsg));

                // 回调信息
                ReturnInfo returnInfo;
                if (pRspInfo != null && pRspInfo.ErrorID != 0)
                {
                    returnInfo = ReturnInfo.Create(false, ErrorCode.PlaceOrderRejectByCTP, pRspInfo.ErrorMsg);
                }
                else
                {
                    returnInfo = ReturnInfo.Create(false, ErrorCode.PlaceOrderRejectByCTP);
                }

                // 下单信息
                OrderStatus status = new OrderStatus();
                status.OrderID = "";
                status.OrderRef = pInputOrder.OrderRef;
                status.OrderState = OrderState.PlaceRejected;
                status.TimeStamp = "";
                status.Message = returnInfo.ErrorMessage;

                ResponseManager.Instance.OnOrderStatus(this.TradingAccount, returnInfo, status, nRequestID);

            }
            catch (Exception ex)
            {
                Logger.Instance.WriteInfo("未处理的异常，" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace);
            }
        }

        /// <summary>
        /// 报单错误(Exchange)
        /// </summary>
        void CThostFtdcTraderSpiWrapper.OnErrRtnOrderInsert(CThostFtdcInputOrderFieldWrapper pInputOrder, CThostFtdcRspInfoFieldWrapper pRspInfo)
        {
            try
            {
                Logger.Instance.WriteInfo(string.Format("资金账号{0}下单[交易所废单]响应,OrderRef={1},ErrorMsg={2}", this.TradingAccount, pInputOrder.OrderRef, pRspInfo.ErrorMsg));

                // 回调信息
                ReturnInfo returnInfo;
                if (pRspInfo != null)
                {
                    returnInfo = ReturnInfo.Create(false, ErrorCode.PlaceOrderRejectByCTP, pRspInfo.ErrorMsg);
                }
                else
                {
                    returnInfo = ReturnInfo.Create(false, ErrorCode.PlaceOrderRejectByCTP);
                }

                // 下单信息
                OrderStatus status = new OrderStatus();
                status.OrderID = "";
                status.OrderRef = pInputOrder.OrderRef;
                status.OrderState = OrderState.PlaceRejected;
                status.TimeStamp = "";
                status.Message = returnInfo.ErrorMessage;

                ResponseManager.Instance.OnOrderStatus(this.TradingAccount, returnInfo, status, pInputOrder.RequestID);

            }
            catch (Exception ex)
            {
                Logger.Instance.WriteInfo("未处理的异常，" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace);
            }
        }

        // 报单、撤单指令已接受 (ctp or Exchange)
        void CThostFtdcTraderSpiWrapper.OnRtnOrder(CThostFtdcOrderFieldWrapper pOrder)
        {
            try
            {
                Logger.Instance.WriteInfo(
                   string.Format("资金资{0}下单/撤单响应,OrderRef={1},ordersubmitstatus={2},orderstatus={3},ordersysid={4},message={5}",
                   this.TradingAccount,
                   pOrder.OrderRef,
                   (char)pOrder.OrderSubmitStatus,
                   (char)pOrder.OrderStatus,
                   pOrder.OrderSysID,
                   pOrder.StatusMsg));

                // 下单信息
                OrderState state = FieldConverter.FromTThostFtdcOrderStatus((TThostFtdcOrderStatus)pOrder.OrderStatus);
                OrderStatus status = new OrderStatus();
                status.OrderID = pOrder.OrderSysID;
                status.OrderRef = pOrder.OrderRef;
                status.OrderState = state;
                status.TimeStamp = pOrder.UpdateTime;
                status.Message = pOrder.StatusMsg;
                status.ExchangeID = pOrder.ExchangeID;

                ReturnInfo returnInfo = ReturnInfo.Create(true, 0);
                ResponseManager.Instance.OnOrderStatus(this.TradingAccount, returnInfo, status, pOrder.RequestID);

            }
            catch (Exception ex)
            {
                Logger.Instance.WriteInfo("未处理的异常，" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace);
            }
        }

        //成交回报、撤单回报
        void CThostFtdcTraderSpiWrapper.OnRtnTrade(CThostFtdcTradeFieldWrapper pTrade)
        {
            try
            {
                Logger.Instance.WriteInfo(string.Format("资金资{0}收到成交回报,OrderSysID={1},Volume={2},Price={3},OrderRef={4}",
                    this.TradingAccount, pTrade.OrderSysID, pTrade.Volume, pTrade.Price, pTrade.OrderRef));

                OrderReport rpt = new OrderReport();
                rpt.Account = this.TradingAccount;
                rpt.Price = pTrade.Price;
                rpt.FilledQuantity = pTrade.Volume;
                rpt.Note = "";
                rpt.OpenClose = FieldConverter.FromTThostFtdcOffsetFlagType((TThostFtdcOffsetFlagType)pTrade.OffsetFlag);
                rpt.OrderID = pTrade.OrderSysID;
                rpt.OrderRef = pTrade.OrderRef;
                rpt.Side = FieldConverter.FromTFtdcDirectionType((TFtdcDirectionType)pTrade.Direction);

                ReturnInfo returnInfo = ReturnInfo.Create(true, 0);
                ResponseManager.Instance.OnOrderFilled(this.TradingAccount, returnInfo, rpt);

            }
            catch (Exception ex)
            {
                Logger.Instance.WriteInfo("未处理的异常，" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace);
            }
        }

        /// <summary>
        /// 撤单拒绝(CTP)
        /// </summary>
        void CThostFtdcTraderSpiWrapper.OnRspOrderAction(CThostFtdcInputOrderActionFieldWrapper pInputOrderAction, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            try
            {
                Logger.Instance.WriteInfo(string.Format("资金账号{0}撤单[CTP废单]响应,OrderActionRef={1},OrderRef={2},OrderSysID={3}",
                    this.TradingAccount,
                    pInputOrderAction.OrderActionRef,
                    pInputOrderAction.OrderRef,
                    pInputOrderAction.OrderSysID));

                // 回调信息
                ReturnInfo returnInfo;
                if (pRspInfo != null)
                {
                    returnInfo = ReturnInfo.Create(false, ErrorCode.CancelOrderRejectByCTP, pRspInfo.ErrorMsg);
                }
                else
                {
                    returnInfo = ReturnInfo.Create(false, ErrorCode.CancelOrderRejectByCTP);
                }

                // 撤单信息
                OrderStatus orderStatus = new OrderStatus();
                orderStatus.OrderID = pInputOrderAction.OrderSysID;
                orderStatus.OrderRef = pInputOrderAction.OrderRef;
                orderStatus.OrderState = OrderState.CancelRejected;
                orderStatus.TimeStamp = "";
                orderStatus.Message = returnInfo.ErrorMessage;

                ResponseManager.Instance.OnOrderStatus(this.TradingAccount, returnInfo, orderStatus, nRequestID);

            }
            catch (Exception ex)
            {
                Logger.Instance.WriteInfo("未处理的异常，" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace);
            }
        }

        //撤单错误(Exchange)
        void CThostFtdcTraderSpiWrapper.OnErrRtnOrderAction(CThostFtdcOrderActionFieldWrapper pOrderAction, CThostFtdcRspInfoFieldWrapper pRspInfo)
        {
            try
            {
                Logger.Instance.WriteInfo(string.Format("资金账号{0}撤单[Exchange废单]响应,OrderActionRef={1}", this.TradingAccount, pOrderAction.OrderActionRef));

                // 回调信息
                ReturnInfo returnInfo;
                if (pRspInfo != null)
                {
                    returnInfo = ReturnInfo.Create(false, ErrorCode.CancelOrderRejectByCTP, pRspInfo.ErrorMsg);
                }
                else
                {
                    returnInfo = ReturnInfo.Create(false, ErrorCode.CancelOrderRejectByCTP);
                }

                // 撤单信息
                OrderStatus orderStatus = new OrderStatus();
                orderStatus.OrderID = pOrderAction.OrderSysID;
                orderStatus.OrderRef = pOrderAction.OrderRef;
                orderStatus.OrderState = OrderState.CancelRejected;
                orderStatus.TimeStamp = "";
                orderStatus.Message = returnInfo.ErrorMessage;

                ResponseManager.Instance.OnOrderStatus(this.TradingAccount, returnInfo, orderStatus, pOrderAction.RequestID);

            }
            catch (Exception ex)
            {
                Logger.Instance.WriteInfo("未处理的异常，" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace);
            }
        }

        #endregion

        #region 私有方法 - 回报 - 查持仓

        // 报单临时缓存，因为报单查询是分页查询，会有多次响应，
        // 所以要把不是最后一次响应的报单缓存起来，
        // 等到最后一次响应时再一次性回调给客户系统
        private ConcurrentDictionary<int, List<PositionInformation>> m_qryPosTempBuff = new ConcurrentDictionary<int, List<PositionInformation>>();

        // 查持仓响应
        void CThostFtdcTraderSpiWrapper.OnRspQryInvestorPosition(CThostFtdcInvestorPositionFieldWrapper pInvestorPosition, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            try
            {
                Logger.Instance.WriteInfo(
                    string.Format(
                        "资金账号{0}收到查持仓响应,requestid={1}，bIsLast={2},pRspInfo.ErrorID={3}",
                        this.TradingAccount,
                        nRequestID,
                        bIsLast,
                        pRspInfo == null ? "null" : pRspInfo.ErrorID.ToString()));

                if (pRspInfo != null && pRspInfo.ErrorID != 0)
                {
                    // 查询失败
                    if (bIsLast)
                    {
                        ReturnInfo returnInfo = ReturnInfo.Create(false, ErrorCode.QueryTodayOrderFailt);
                        ResponseManager.Instance.OnPosition(this.TradingAccount, returnInfo, new PositionInformation[] { }, nRequestID);
                    }
                }
                else
                {
                    if (!m_qryPosTempBuff.ContainsKey(nRequestID))
                    {
                        m_qryPosTempBuff.TryAdd(nRequestID, new List<PositionInformation>());
                    }

                    List<PositionInformation> list = m_qryPosTempBuff[nRequestID];

                    if (pInvestorPosition != null)
                    {
                        // 获取响应的委托单
                        PositionInformation pos = new PositionInformation();
                        pos.UserAccount = pInvestorPosition.InvestorID;
                        pos.Symbol = pInvestorPosition.InstrumentID;
                        pos.Unit = Unit.Hand;
                        pos.PosSide = FieldConverter.FromTThostFtdcPosiDirection((TThostFtdcPosiDirection)pInvestorPosition.PosiDirection);
                        pos.PositionDate = pInvestorPosition.PositionDate == (sbyte)'1' ? PositionDateType.UseHistory : PositionDateType.NoUseHistory;
                        pos.YdPosition = pInvestorPosition.YdPosition;
                        pos.TodayPosition = (double)pInvestorPosition.Position;
                        pos.MoreFrozen = pInvestorPosition.LongFrozen;
                        pos.ShortFrozen = pInvestorPosition.ShortFrozen;
                        pos.OpenFrozenAmount = pInvestorPosition.LongFrozenAmount;
                        pos.CloseFrozenAmount = pInvestorPosition.ShortFrozenAmount;
                        pos.OpenVolume = (double)pInvestorPosition.OpenVolume;
                        pos.CloseVolume = pInvestorPosition.CloseVolume;
                        pos.PositionCose = pInvestorPosition.PositionCost;
                        pos.PreMargin = pInvestorPosition.PreMargin;
                        pos.UseMargin = pInvestorPosition.UseMargin;
                        list.Add(pos);
                    }

                    // 只有最后一次响应才回调到客户端
                    if (bIsLast)
                    {
                        Logger.Instance.WriteDebug(string.Format("向客户端发送持仓数据,共{0}条记录", list.Count));
                        ReturnInfo returnInfo = ReturnInfo.Create(true, 0);

                        m_qryPosTempBuff.TryRemove(nRequestID, out list);
                        ResponseManager.Instance.OnPosition(this.TradingAccount, returnInfo, list.ToArray(), nRequestID);
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Instance.WriteInfo("未处理的异常，" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace);
            }
        }

        #endregion

        #region 私有方法 - 回报 - 报单查询响应

        // 报单临时缓存，因为报单查询是分页查询，会有多次响应，
        // 所以要把不是最后一次响应的报单缓存起来，
        // 等到最后一次响应时再一次性回调给客户系统
        private ConcurrentDictionary<int, List<Order>> m_qryOrderTempBuff = new ConcurrentDictionary<int, List<Order>>();

        // 报单查询响应
        void CThostFtdcTraderSpiWrapper.OnRspQryOrder(CThostFtdcOrderFieldWrapper pOrder, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            try
            {
                Logger.Instance.WriteInfo(string.Format("资金账号{0}收到报单委托响应,requestid={1}，bIsLast={2},pRspInfo.ErrorID={3}", this.TradingAccount, nRequestID, bIsLast, pRspInfo == null ? "null" : pRspInfo.ErrorID.ToString()));

                if (pRspInfo != null && pRspInfo.ErrorID != 0)
                {
                    // 查询失败
                    if (bIsLast)
                    {
                        ReturnInfo returnInfo = ReturnInfo.Create(false, ErrorCode.QueryTodayOrderFailt);
                        ResponseManager.Instance.OnQueryOrder(this.TradingAccount, returnInfo, new Order[] { }, nRequestID);
                    }
                }
                else
                {
                    if (!m_qryOrderTempBuff.ContainsKey(nRequestID))
                    {
                        m_qryOrderTempBuff.TryAdd(nRequestID, new List<Order>());
                    }

                    List<Order> list = m_qryOrderTempBuff[nRequestID];

                    if (pOrder != null)
                    {
                        // 获取响应的委托单
                        Order ord = new Order();

                        ord.UserAccount = pOrder.InvestorID;
                        ord.Code = pOrder.InstrumentID;
                        ord.Unit = Unit.Hand;
                        ord.OrderID = pOrder.OrderSysID.Trim();
                        ord.OrderRef = pOrder.OrderRef;
                        ord.Amount = pOrder.VolumeTotalOriginal;
                        ord.OrderState = FieldConverter.FromTThostFtdcOrderStatus((TThostFtdcOrderStatus)pOrder.OrderStatus);
                        ord.Side = FieldConverter.FromTFtdcDirectionType((TFtdcDirectionType)pOrder.Direction);
                        ord.FilledAmount = pOrder.VolumeTraded;
                        ord.Price = pOrder.LimitPrice;
                        ord.PriceMode = FieldConverter.FromOrderPriceType((TThostFtdcOrderPriceType)pOrder.OrderPriceType);
                        ord.UpdateTimeStamp = pOrder.UpdateTime;

                        list.Add(ord);
                    }

                    // 只有最后一次响应才回调到客户端
                    if (bIsLast)
                    {
                        ReturnInfo returnInfo = ReturnInfo.Create(true, 0);
                        ResponseManager.Instance.OnQueryOrder(this.TradingAccount, returnInfo, list.ToArray(), nRequestID);
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Instance.WriteInfo("未处理的异常，" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace);
            }

        }
        #endregion

        #region 私有方法 - 回报 - 查成交

        // 查成交临时缓存，因为成交单查询是分页查询，会有多次响应，
        // 所以要把不是最后一次响应的成交缓存起来，
        // 等到最后一次响应时再一次性回调给客户系统
        private ConcurrentDictionary<int, List<OrderReport>> m_qryFilledTempBuff = new ConcurrentDictionary<int, List<OrderReport>>();

        // 查成交响应
        void CThostFtdcTraderSpiWrapper.OnRspQryTrade(CThostFtdcTradeFieldWrapper pTrade, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            try
            {
                Logger.Instance.WriteInfo(
                    string.Format(
                    "资金账号{0}收到查成交响应时,requestid={1}，bIsLast={2},pRspInfo.ErrorID={3}",
                        this.TradingAccount,
                        nRequestID,
                        bIsLast,
                        pRspInfo == null ? "null" : pRspInfo.ErrorID.ToString()));

                if (pRspInfo != null && pRspInfo.ErrorID != 0)
                {
                    // 查询失败
                    if (bIsLast)
                    {
                        ReturnInfo returnInfo = ReturnInfo.Create(false, ErrorCode.QueryTodayOrderFailt);
                        ResponseManager.Instance.OnQueryFilled(this.TradingAccount, returnInfo, new OrderReport[] { }, nRequestID);
                    }
                }
                else
                {
                    if (!m_qryOrderTempBuff.ContainsKey(nRequestID))
                    {
                        m_qryFilledTempBuff.TryAdd(nRequestID, new List<OrderReport>());
                    }

                    List<OrderReport> list = m_qryFilledTempBuff[nRequestID];

                    if (pTrade != null)
                    {
                        // 获取响应的委托单
                        OrderReport ord = new OrderReport();

                        ord.Account = pTrade.InvestorID;
                        ord.Code = pTrade.InstrumentID;
                        ord.OrderID = pTrade.OrderSysID.Trim();
                        ord.OrderRef = pTrade.OrderRef;
                        ord.Side = FieldConverter.FromTFtdcDirectionType((TFtdcDirectionType)pTrade.Direction);
                        ord.OpenClose = FieldConverter.FromTThostFtdcOffsetFlagType((TThostFtdcOffsetFlagType)pTrade.OffsetFlag);

                        ord.Price = pTrade.Price;
                        ord.FilledQuantity = pTrade.Volume;
                        ord.Note = pRspInfo == null ? "" : pRspInfo.ErrorMsg;
                        ord.TimeStamp = pTrade.TradeDate + " " + pTrade.TradeTime;

                        list.Add(ord);
                    }

                    // 只有最后一次响应才回调到客户端
                    if (bIsLast)
                    {
                        ReturnInfo returnInfo = ReturnInfo.Create(true, 0);
                        ResponseManager.Instance.OnQueryFilled(this.TradingAccount, returnInfo, list.ToArray(), nRequestID);
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Instance.WriteInfo("未处理的异常，" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace);
            }

        }

        #endregion

        #region 私有方法 - 回报 - 未处理的回报

        void CThostFtdcTraderSpiWrapper.OnRspQryInstrument(CThostFtdcInstrumentFieldWrapper pInstrument, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            Logger.Instance.WriteInfo("回调方法OnRspQryInstrument未处理");
        }

        void CThostFtdcTraderSpiWrapper.OnRspError(CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            Logger.Instance.WriteInfo("回调方法OnRspError未处理");
        }

        void CThostFtdcTraderSpiWrapper.OnHeartBeatWarning(int nTimeLapse)
        {
            Logger.Instance.WriteInfo("回调方法OnHeartBeatWarning未处理");
        }

        void CThostFtdcTraderSpiWrapper.OnRspParkedOrderAction(CThostFtdcParkedOrderActionFieldWrapper pParkedOrderAction, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            Logger.Instance.WriteInfo("回调方法OnRspParkedOrderAction未处理");
        }

        void CThostFtdcTraderSpiWrapper.OnRspParkedOrderInsert(CThostFtdcParkedOrderFieldWrapper pParkedOrder, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            Logger.Instance.WriteInfo("回调方法OnRspParkedOrderInsert未处理");
        }

        void CThostFtdcTraderSpiWrapper.OnRspQryContractBank(CThostFtdcContractBankFieldWrapper pContractBank, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            Logger.Instance.WriteInfo("回调方法OnRspQryContractBank未处理");
        }

        void CThostFtdcTraderSpiWrapper.OnRspQryDepthMarketData(CThostFtdcDepthMarketDataFieldWrapper pDepthMarketData, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            Logger.Instance.WriteInfo("回调方法OnRspQryDepthMarketData未处理");
        }

        void CThostFtdcTraderSpiWrapper.OnRspQryExchange(CThostFtdcExchangeFieldWrapper pExchange, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            Logger.Instance.WriteInfo("回调方法OnRspQryExchange未处理");
        }

        void CThostFtdcTraderSpiWrapper.OnRspQryInstrumentCommissionRate(CThostFtdcInstrumentCommissionRateFieldWrapper pInstrumentCommissionRate, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            Logger.Instance.WriteInfo("回调方法OnRspQryInstrumentCommissionRate未处理");
        }

        void CThostFtdcTraderSpiWrapper.OnRspQryInstrumentMarginRate(CThostFtdcInstrumentMarginRateFieldWrapper pInstrumentMarginRate, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            Logger.Instance.WriteInfo("回调方法OnRspQryInstrumentMarginRate未处理");
        }

        void CThostFtdcTraderSpiWrapper.OnRspQryInvestor(CThostFtdcInvestorFieldWrapper pInvestor, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            Logger.Instance.WriteInfo("回调方法OnRspQryInvestor未处理");
        }

        void CThostFtdcTraderSpiWrapper.OnRspQryInvestorPositionCombineDetail(CThostFtdcInvestorPositionCombineDetailFieldWrapper pInvestorPositionCombineDetail, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            Logger.Instance.WriteInfo("回调方法OnRspQryInvestorPositionCombineDetail未处理");
        }

        void CThostFtdcTraderSpiWrapper.OnRspQryInvestorPositionDetail(CThostFtdcInvestorPositionDetailFieldWrapper pInvestorPositionDetail, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            Logger.Instance.WriteInfo("回调方法OnRspQryInvestorPositionDetail未处理");
        }

        void CThostFtdcTraderSpiWrapper.OnRspQryNotice(CThostFtdcNoticeFieldWrapper pNotice, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            Logger.Instance.WriteInfo("回调方法OnRspQryNotice未处理");
        }

        void CThostFtdcTraderSpiWrapper.OnRspQryParkedOrder(CThostFtdcParkedOrderFieldWrapper pParkedOrder, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            Logger.Instance.WriteInfo("回调方法OnRspQryParkedOrder未处理");
        }

        void CThostFtdcTraderSpiWrapper.OnRspQryParkedOrderAction(CThostFtdcParkedOrderActionFieldWrapper pParkedOrderAction, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            Logger.Instance.WriteInfo("回调方法OnRspQryParkedOrderAction未处理");
        }

        void CThostFtdcTraderSpiWrapper.OnRspQrySettlementInfo(CThostFtdcSettlementInfoFieldWrapper pSettlementInfo, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            Logger.Instance.WriteInfo("回调方法OnRspQrySettlementInfo未处理");
        }

        void CThostFtdcTraderSpiWrapper.OnRspQryTradingCode(CThostFtdcTradingCodeFieldWrapper pTradingCode, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            Logger.Instance.WriteInfo("回调方法OnRspQryTradingCode未处理");
        }

        void CThostFtdcTraderSpiWrapper.OnRspQryTradingNotice(CThostFtdcTradingNoticeFieldWrapper pTradingNotice, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            Logger.Instance.WriteInfo("回调方法OnRspQryTradingNotice未处理");
        }

        void CThostFtdcTraderSpiWrapper.OnRspQryTransferBank(CThostFtdcTransferBankFieldWrapper pTransferBank, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            Logger.Instance.WriteInfo("回调方法OnRspQryTransferBank未处理");
        }

        void CThostFtdcTraderSpiWrapper.OnRspQueryMaxOrderVolume(CThostFtdcQueryMaxOrderVolumeFieldWrapper pQueryMaxOrderVolume, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            Logger.Instance.WriteInfo("回调方法OnRspQueryMaxOrderVolume未处理");
        }

        void CThostFtdcTraderSpiWrapper.OnRspRemoveParkedOrder(CThostFtdcRemoveParkedOrderFieldWrapper pRemoveParkedOrder, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            Logger.Instance.WriteInfo("回调方法OnRspRemoveParkedOrder未处理");
        }

        void CThostFtdcTraderSpiWrapper.OnRspRemoveParkedOrderAction(CThostFtdcRemoveParkedOrderActionFieldWrapper pRemoveParkedOrderAction, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            Logger.Instance.WriteInfo("回调方法OnRspRemoveParkedOrderAction未处理");
        }

        void CThostFtdcTraderSpiWrapper.OnRspTradingAccountPasswordUpdate(CThostFtdcTradingAccountPasswordUpdateFieldWrapper pTradingAccountPasswordUpdate, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            Logger.Instance.WriteInfo("回调方法OnRspTradingAccountPasswordUpdate未处理");
        }

        void CThostFtdcTraderSpiWrapper.OnRspTransferBankToFuture(CThostFtdcTransferBankToFutureRspFieldWrapper pTransferBankToFutureRsp, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            Logger.Instance.WriteInfo("回调方法OnRspTransferBankToFuture未处理");
        }

        void CThostFtdcTraderSpiWrapper.OnRspTransferFutureToBank(CThostFtdcTransferFutureToBankRspFieldWrapper pTransferFutureToBankRsp, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            Logger.Instance.WriteInfo("回调方法OnRspTransferFutureToBank未处理");
        }

        void CThostFtdcTraderSpiWrapper.OnRspTransferQryBank(CThostFtdcTransferQryBankRspFieldWrapper pTransferQryBankRsp, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            Logger.Instance.WriteInfo("回调方法OnRspTransferQryBank未处理");
        }

        void CThostFtdcTraderSpiWrapper.OnRspTransferQryDetail(CThostFtdcTransferQryDetailRspFieldWrapper pTransferQryDetailRsp, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            Logger.Instance.WriteInfo("回调方法OnRspTransferQryDetail未处理");
        }

        void CThostFtdcTraderSpiWrapper.OnRspUserPasswordUpdate(CThostFtdcUserPasswordUpdateFieldWrapper pUserPasswordUpdate, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            Logger.Instance.WriteInfo("回调方法OnRspUserPasswordUpdate未处理");
        }

        void CThostFtdcTraderSpiWrapper.OnRtnInstrumentStatus(CThostFtdcInstrumentStatusFieldWrapper pInstrumentStatus)
        {
            Logger.Instance.WriteInfo("回调方法OnRtnInstrumentStatus未处理");
        }

        void CThostFtdcTraderSpiWrapper.OnRtnTradingNotice(CThostFtdcTradingNoticeInfoFieldWrapper pTradingNoticeInfo)
        {
            Logger.Instance.WriteInfo("回调方法OnRtnTradingNotice未处理");
        }

        #endregion
    }
}
